package test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @author zengfh
 * @version 1.0
 * date 2018/04/23 09:46
 */
public class NioService {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(NioService.class);
    
    public static void main(String[] args) throws IOException {
        new NioService().init();
    }
    
    
    public void init() throws IOException {
    
        Selector selector = Selector.open();
    
        ServerSocketChannel server = ServerSocketChannel.open();
        
        server.socket().bind(new InetSocketAddress(7777), 1024);
        
        server.configureBlocking(false);
        
        server.register(selector, SelectionKey.OP_ACCEPT);
        
        while (true) {
            selector.select(1000);
            Set<SelectionKey> keys = selector.selectedKeys();
    
            Iterator<SelectionKey> iterator = keys.iterator();
            SelectionKey key = null;
            while (iterator.hasNext()) {
    
                key = iterator.next();
                iterator.remove();
                
                if (key.isAcceptable()){
                    ServerSocketChannel ssc = (ServerSocketChannel)key.channel();
                    SocketChannel accept = ssc.accept();
                    accept.configureBlocking(false);
                    accept.register(selector, SelectionKey.OP_READ);
                    
                    key.interestOps(SelectionKey.OP_ACCEPT);
                    
                    
                }
    
    
                if (key.isReadable()) {
                    SocketChannel channel = (SocketChannel) key.channel();
                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                    String content = "";
                    try {
                        int readBytes = channel.read(byteBuffer);
                        if (readBytes > 0) {
                            byteBuffer.flip(); //为write()准备
                            byte[] bytes = new byte[byteBuffer.remaining()];
                            byteBuffer.get(bytes);
                            content+=new String(bytes);
                            System.out.println(content);
                            //回应客户端
                            doWrite(channel);
                        }
                        // 写完就把状态关注去掉，否则会一直触发写事件(改变自身关注事件)
                        key.interestOps(SelectionKey.OP_READ);
                    } catch (IOException i) {
                        //如果捕获到该SelectionKey对应的Channel时出现了异常,即表明该Channel对于的Client出现了问题
                        //所以从Selector中取消该SelectionKey的注册
                        key.cancel();
                        if (key.channel() != null) {
                            key.channel().close();
                        }
                    }
                }
            }
    
    
        }
        
    }
    
    private  void doWrite(SocketChannel sc) throws IOException{
        byte[] req ="服务器已接受".getBytes();
        ByteBuffer byteBuffer = ByteBuffer.allocate(req.length);
        byteBuffer.put(req);
        byteBuffer.flip();
        sc.write(byteBuffer);
        if(!byteBuffer.hasRemaining()){
            System.out.println("Send 2 Service successed");
        }
    }
}
